# 把一个 JSON 数据集转换成一个嵌套着FrozenJSON 对象、列表和简单类型的 FrozenJSON 对象
import keyword
from collections import abc
from osconfeed import load


class FrozenJson:

    def __new__(cls, arg): # 第一个参数类本身 余下的参数与 __init__一样
        # 替代build方法
        if isinstance(arg, abc.Mapping):
            return super().__new__(cls)
        elif isinstance(arg, abc.MutableSequence):
            return [cls(item) for item in arg]
        else:
            return arg

    def __init__(self, mapping):
        self.__data = {}
        # 处理关键字
        for key, value in mapping.items():
            if keyword.iskeyword(key):
                key += '_'
            self.__data[key] = value

    def __getattr__(self, name):  # 仅当没有指定名称（name）的属性时才调用 __getattr__ 方法
        if hasattr(self.__data, name):
            return getattr(self.__data, name)
        else:
            # return FrozenJson.build(self.__data[name])
            return FrozenJson(self.__data[name])

    @classmethod
    def build(cls, obj):
        if isinstance(obj, abc.Mapping):
            return cls(obj)
        elif isinstance(obj, abc.MutableSequence):
            return [cls.build(item) for item in obj]
        else:
            return obj


if __name__ == '__main__':
    raw_feed = load()
    feed = FrozenJson(raw_feed)
    print(len(feed.Schedule.speakers))
    print(sorted(feed.Schedule.keys()))
    for key, value in sorted(feed.Schedule.items()):
        print('{:3} {}'.format(len(value), key))
    print(feed.Schedule.speakers[-1].name)
    talk = feed.Schedule.events[40]
    print(type(talk))
    print(talk.name)
    print(talk.speakers)
    print(talk.flavor)
